#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <netdb.h>
#include <signal.h>
#include <libgen.h>

#include "mosquitto.h"
#include "ds18b20.h"
#include "cJSON.h"
#include "iniparser.h"
#include "configoperate.h"


#define INI_PATH "./mqtt_aliyun_conf.ini"
#define KEEP_ALIVE 60




int g_stop = 0;

static inline void print_usage(char *progname);//内联函数，空间换时间。编译时期展开。

void sig_handler(int sig_num)
{
    if(sig_num == SIGUSR1)
        g_stop = 1;

}

void connect_callback(struct mosquitto *mosq,void *obj,int rc);


int main (int argc, char **argv)
{

    char        *progname = basename(argv[0]);
    
    
    int                         brokerport = 0;
    char                        *brokeraddress = NULL;
    char                        *clientid = NULL;
    char                        *username = NULL;
    char                        *password = NULL;


    char                        *topic = NULL;
    struct mosquitto            *mosq = NULL;
    int                         daemon_run = 0;
    int                         opt = -1;
    int                         rv;
    char                        buffer[BUF_SIZE];
    int                         log_fd;
    
    struct mqtt_user_data       mqtt;


     struct option options[] = 
     {
         {"daemon",no_argument,NULL,'d'},
         {"topic", required_argument,NULL,'t'},
         {"brokeraddress", required_argument,NULL,'H'},
         {"clientid", required_argument, NULL, 'i'},
         {"brokerport",required_argument,NULL,'p'},
         {"help",no_argument,NULL,'h'},
         {"username",required_argument,NULL,'u'},
         {"password",required_argument,NULL,'P'},
         {NULL,0,NULL,0}
     };



     while((opt = getopt_long(argc,argv,"dhp:t:i:u:P:H:",options,NULL)) != -1)
     {
        
         switch(opt)
         
         {

             case 't':
                 topic = optarg;
                 break;

             case 'i':
                 clientid = optarg;
                 break;

             case 'H':
                 brokeraddress = optarg;
                 break;
             case 'u':
                 username = optarg;
                 break;
            case 'P':
                 password = optarg;
                 break;

             case 'd':
                 daemon_run = 1;
                 break;
             case 'p':
                 brokerport = atoi(optarg);
                 break;
             case 'h':
                 print_usage(argv[0]);
                 return 0;
             default:
                 break;
         }
     }

    
     //set_config(INI_PATH,brokeraddress,brokerport,clientid,username,password,topic);
    

     if(daemon_run)
     {
         printf("program %s running in backgrund\n", progname);
         if( (log_fd = open("client.log", O_CREAT|O_RDWR, 0666)) < 0)
         {
             printf("open() failed:%s\n", strerror(errno)) ;
             return -2;
         }

        dup2(log_fd, STDOUT_FILENO) ;
        dup2(log_fd, STDERR_FILENO) ;

         daemon(1,1);
     }
     
    
     signal(SIGUSR1,sig_handler);


     memset(&mqtt,0,sizeof(mqtt));


     rv = get_config(INI_PATH,&mqtt,PUB);



     mosquitto_lib_init();
     mosq = mosquitto_new(mqtt.clientid,true,(void *)&mqtt);
     if(!mosq)
     {
         printf("mosquitto_new() failed: %s\n",strerror(errno));
         mosquitto_lib_cleanup();
         return -1;
     }


     if(mosquitto_username_pw_set(mosq,mqtt.username,mqtt.password) != MOSQ_ERR_SUCCESS)
     {
         printf("mosquitto_username_pw_set failed: %s\n",strerror(errno));
         /*mosquitto_destroy(mosq);
         mosquitto_lib_cleanup();
         return -1;*/
         goto   cleanup;
     }
     printf("Create mosquitto successfully!\n");
    
     mosquitto_connect_callback_set(mosq,connect_callback);

     /*if(mosquitto_loop_start(mosq) != MOSQ_ERR_SUCCESS)
     {

                printf("mosquitto_loop_start() failed: %s\n",strerror(errno));
                //mosquitto_destroy(mosq);
                //mosquitto_lib_cleanup();
                //return -1;
                goto cleanup;
     }
    
     printf("mosquitto_loop_start() successfully!\n");*/
        
     //printf("%s\n",brokeraddress);
     //printf("%d\n",brokerport);
     while(!g_stop)
     {
         printf("into while:\n");
        if(mosquitto_connect(mosq, mqtt.brokeraddress,mqtt.brokerport,KEEP_ALIVE) != MOSQ_ERR_SUCCESS)
        {
            printf("mosquitto_connect() failed: %s\n",strerror(errno));
            //continue;
            goto cleanup;
            
        }
        printf("connect successfully\n");
        mosquitto_loop_forever(mosq,-1,1);
        sleep(30);
     }

cleanup:
    close(log_fd);
    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();
     return 0;
} 

void print_usage(char *progname)
{
    printf("%s usage:\n",progname);
    printf("Example: %s -h ${brokeraddress} -p ${brokerport} -i ${clientid} -u ${username} -p ${password} -t${topic} -h ${help} -d ${daemon}\n",progname);
    printf("-h(--host): sepcify brokeraddress.\n");
    printf("-p(--port): sepcify brokerport.\n");
    printf("-h(--Help): print this help information.\n");
    printf("-d(--daemon): set program running on background.\n");
    printf("-i(--clientid): sepcify the clientid.\n");
    printf("-u(--username): sepcify username of the client.\n");
    printf("-p(--password): sepcify password of the username.\n");
    printf("-t(--topic): sepcify topic of the client.\n");
    printf("-d(--daemon): running in backgrund.\n");
}

void connect_callback(struct mosquitto *mosq,void *obj,int rc)
{
    printf("get into connect_callback():\n");
    
    float t = 27.000000;

    if(ds18b20_get_temperature(&t) < 0)
    {
        printf("ds18b20_get_temperature failed.\n");
        return;
    }


    cJSON   *root = cJSON_CreateObject();
    cJSON   *item = cJSON_CreateObject();


    if(!obj)
    {
        printf("invalid_argument in %s\n",__FUNCTION__);
        return;
    }

    struct mqtt_user_data *mqtt = (mqtt_user_data *)obj;

    cJSON_AddItemToObject(root,"method",cJSON_CreateString(mqtt->method));
    cJSON_AddItemToObject(root,"id",cJSON_CreateString(mqtt->jsonid));
    cJSON_AddItemToObject(root,"params",item);
    cJSON_AddItemToObject(item,"CurrentTemperature",cJSON_CreateNumber(t));
    cJSON_AddItemToObject(root,"version",cJSON_CreateString(mqtt->version));
    char *msg = cJSON_Print(root);
    printf("%s\n",msg);


    if(!rc)
    {
        if(mosquitto_publish(mosq,NULL,mqtt->topic,strlen(msg),msg,0,NULL) != MOSQ_ERR_SUCCESS)
        {
            printf("mosquitto_publish failed: %s\n",strerror(errno));
            return;
        }
    }

    mosquitto_disconnect(mosq);

}

